/**
 * https://book.kotlincn.net/text/d-basic-types.html
 * 概念 -> 类型 -> 基本类型
 */

/**
 * 数字 -> 整数类型
 */
fun main41() {
    /**
     * 类型   大小(比特数) 最小值	                        最大值
     * Byte     8          -128                         127
     * Short    16        -32768                        32767
     * Int      32  -2,147,483,648(-2³¹)                2,147,483,647(2³¹ - 1)
     * Long     64  -9,223,372,036,854,775,808(-2⁶³)    9,223,372,036,854,775,807 (2⁶³ - 1)
     */
    val one = 1                     // Int
    val threeBillion = 3000000000   // Long
    val oneLong = 1L                // Long
    val oneByte: Byte = 1

    /**
     * UByte : 无符号 8  比特整数，范围是 0 到 255
     * UShort: 无符号 16 比特整数，范围是 0 到 65535
     * UInt  : 无符号 32 比特整数，范围是 0 到 2^32 - 1
     * ULong : 无符号 64 比特整数，范围是 0 到 2^64 - 1
     */
    val ub: UByte = 1u      // UByte，已提供预期类型
    val us: UShort = 1u     // UShort，已提供预期类型
    val ul: ULong = 1u      // ULong，已提供预期类型

    val a1 = 42u                // UInt：未提供预期类型，常量适于 UInt
    val a2 = 0xFFFF_FFFF_FFFFu  // ULong：未提供预期类型，常量不适于 UInt
    val a = 1UL                 // ULong，即使未提供预期类型并且常量适于 UInt

    /**
     * UByteArray: 无符号字节数组
     * UShortArray: 无符号短整型数组
     * UIntArray: 无符号整型数组
     * ULongArray: 无符号长整型数组
     */
    val uByteArray = ubyteArrayOf(ub)
}


/**
 * 浮点类型
 */
fun main42() {
    /**
     * 类型   大小(比特数)    有效数字比特数  指数比特数   十进制位数
     * Float    32              24              8       6-7
     * Double   64              53              11      15-16
     */
    val eFloat = 2.7182818284F  // Float，实际值为 2.7182817
    val e = 2.7182818284        // Double
    val pi = 3.14               // Double
    //val one: Double = 1       // 错误：类型不匹配
    val oneDouble = 1.0         // Double

    /**
     * 与一些其他语言不同，Kotlin 中的数字没有隐式拓宽转换。
     * 例如，具有 Double 参数的函数只能对 Double 值调用，而不能对 Float、 Int 或者其他数字值调用：
     */
    fun printDouble(d: Double) { print(d) }

    val i = 1
    val d = 1.0
    val f = 1.0f

    printDouble(d)
//    printDouble(i)    // 错误：类型不匹配
//    printDouble(f)    // 错误：类型不匹配
}


/**
 * 数字字面常量
 */
fun main43() {
    //数值常量字面值有以下几种:
    val bin = 0b00001011    //二进制 Int
    //Kotlin 不支持八进制。
    val int = 123           //十进制
    val hex = 0x0F          //十六进制 Int
    val long = 123L         //Long 类型用大写 L 标记

    //你可以使用下划线使数字常量更易读：
    val oneMillion           = 1_000_000
    val creditCardNumber     = 1234_5678_9012_3456L
    val socialSecurityNumber = 999_99_9999L
    val hexBytes             = 0xFF_EC_DE_5E
    val bytes                = 0b11010010_01101001_10010100_10010010
}


/**
 * JVM 平台的数字表示
 */
fun main44() {
    //对相同数字的可为空引用可能会引用不同的对象：
    val a: Int = 100
    val boxedA: Int? = a
    val anotherBoxedA: Int? = a

    val b: Int = 10000
    val boxedB: Int? = b
    val anotherBoxedB: Int? = b

    /**
     * 由于 JVM 对 -128 到 127 的整数（Integer）应用了内存优化，
     * 因此，a 的所有可空引用实际上都是同一对象。
     * 但是没有对 b 应用内存优化，所以它们是不同对象。
     */
    println(boxedA === anotherBoxedA) // true
    println(boxedB === anotherBoxedB) // false


    /**
     * 由于 JVM 对 -128 到 127 的整数（Integer）应用了内存优化，
     * 因此，a 的所有可空引用实际上都是同一对象。
     * 但是没有对 b 应用内存优化，所以它们是不同对象。
     */
    //另一方面，它们仍然相等:
    val c: Int = 10000
    println(c == c)                     //true
    val boxedB2: Int? = c
    val anotherBoxedB2: Int? = c
    println(boxedB2 == anotherBoxedB2)  //true
}


/**
 * 显式数字转换
 */
fun main45() {
    //由于不同的表示方式，较小类型并不是较大类型的子类型。 如果它们是的话，就会出现下述问题：
    // 假想的代码，实际上并不能编译：
//    val a: Int? = 1 // 一个装箱的 Int (java.lang.Integer)
//    val b: Long? = a // 隐式转换产生一个装箱的 Long (java.lang.Long)
//    print(b == a) // 惊！这将输出“false”鉴于 Long 的 equals() 会检测另一个是否也为 Long

    val b: Byte = 1 // OK, 字面值会静态检测
    // val i: Int = b // 错误
    val i1: Int = b.toInt()

    /**
     * 所有数字类型都支持转换为其他类型：
     * toByte(): Byte
     * toShort(): Short
     * toInt(): Int
     * toLong(): Long
     * toFloat(): Float
     * toDouble(): Double
     */
    //很多情况都不需要显式类型转换，因为类型会从上下文推断出来， 而算术运算会有重载做适当转换，例如：
    val l = 1L + 3 // Long + Int => Long
}


/**
 * 整数除法
 */
fun main46() {
    val x = 5L / 2
    println(x == 2L)        //true

    val y = 5 / 2.toDouble()
    println(y == 2.5)       //true
}


/**
 * 位运算
 */
fun main47() {
    /**
     * Kotlin 对整数提供了一组位运算。它们直接使用数字的比特表示在二进制级别进行操作。
     * 位运算有可以通过中缀形式调用的函数表示。只能应用于 Int 与 Long：
     * shl(bits)  – 有符号左移 signed   left
     * shr(bits)  – 有符号右移 signed   right
     * ushr(bits) – 无符号右移 unsigned right
     * and(bits)  – 位与       and
     * or(bits)   – 位或       or
     * xor(bits)  – 位异或     ?
     * inv()      – 位非       ?
     */
    val x = (1 shl 2) and 0x000FF000
}


/**
 * 浮点数比较
 * 相等性检测：a == b 与 a != b
 * 比较操作符：a < b、 a > b、 a <= b、 a >= b
 * 区间实例以及区间检测：a..b、  x in a..b、  x !in a..b
 */
fun main48() {
    println(Double.NaN == Double.NaN)                 //false   boolean var0 = Double.NaN == Double.NaN;
    println(listOf(Double.NaN) == listOf(Double.NaN)) //true    boolean var0 = Intrinsics.areEqual(CollectionsKt.listOf(Double.NaN), CollectionsKt.listOf(Double.NaN));

    println(0.0 == -0.0)                              //true    boolean var0 = 0.0D == -0.0D;
    println(listOf(0.0) == listOf(-0.0))              //false   boolean var0 = Intrinsics.areEqual(CollectionsKt.listOf(0.0D), CollectionsKt.listOf(-0.0D));

    /**
     * [-0.0, 0.0, Infinity, NaN]
     * List var2 = CollectionsKt.sorted((Iterable)CollectionsKt.listOf(new Double[]{Double.NaN, Double.POSITIVE_INFINITY, 0.0D, -0.0D}));
     */
    println(listOf(Double.NaN, Double.POSITIVE_INFINITY, 0.0, -0.0).sorted())
}
